/*
 * PathFinder.h
 *
 *  Created on: 2.2.2013
 *      Author: Atomic
 */

#pragma once

#ifdef _WIN32 
#include <windows.h> 
#include "SDL_thread.h"
#else

#include "SDL/SDL_thread.h"

#endif

#include <list>
#include <glm/glm.hpp>
#include "../Terrain.h"
#include <vector>
#include <math.h>
#include <algorithm>
#include <iostream>
#include <list>
#include <map>

//-------------------------!-

#define RESERVED	0
#define FREE		1
#define WATER		69

struct Node
{
	int walkability;
	int terrainCost;
	void *object;
};

class PathFinder
{
public:
	PathFinder(Terrain::Terrain *_terrain);

	virtual ~PathFinder();

	//Map walkability update function
	void updateMapData(float waterLevel);

	//Get path for entity
	std::list<glm::vec2> getPath(glm::vec2 targetVector, glm::vec2 beginVector);

	//Pointer to terrain, where pathfinding will be performed
	Terrain::Terrain *terrain;

	bool CheckBuildingPosition(DataTypes::Cube *cubePlace, glm::vec2 pos);
	bool ReserveBuildingPosition(DataTypes::Cube *cubePlace, glm::vec2 pos,
			void* obj);
	void FreeBuildingPosition(DataTypes::Cube *cubePlace, glm::vec2 pos);

	void* getNearestEntityOfType(glm::vec2 pos, int r, int objtype);
	void* getNearestEntityOfType(glm::vec2 pos, int r, int type, int status,
			bool chckParetType);
	std::vector<void*> getEntityOfTypeInArea(glm::vec2 pos, int r, int type,
			int status);
	glm::vec2 getNearestFreePoint(glm::vec2 pos);
	bool uniqueInVector(std::vector<void *> input, void* data);

	void ReadPath(int pathfinderID, int currentX, int currentY,
			int pixelsPerFrame);
	int ReadPathX(int pathfinderID, int pathLocation);
	int ReadPathY(int pathfinderID, int pathLocation);

	//Include pointer to entity object, casted as *void and retyped inside. For recognition of unit 
	//holding specific place on map(for ex. tree)
	int ReservePosition(int x, int y, void* entityObject);
	int ReservePosition(int x, int y);

	void FreePosition(int x, int y);
	int FindPath(int pathfinderID, int startingX, int startingY, int targetX,
			int targetY);
	//int ReverseFindPath (int pathfinderID,int startingX, int startingY, int targetX, int targetY);
	void EndPathfinder(void);
	void InitializePathfinder(void);
	glm::vec2 FindWalkablePos(int tx, int ty, int bx, int by);

	//}

private:

	Node **node;

	float ter2d[MAXSIZE][MAXSIZE];
	int *openList;
	int **whichList;
	int *openX;
	int *openY;
	int **parentX;
	int **parentY;
	int *Fcost;
	int **Gcost;
	int *Hcost;

	int pathLength[1 + 1]; //stores length of the found path
	int pathLocation[1 + 1]; //stores current position
	int* pathBank[1 + 1]; //final path;
	//Path reading variable
	int pathStatus[1 + 1];
	int xPath[1 + 1];
	int yPath[1 + 1];

	bool nodeExists(int x, int y);
	bool nodeIsWalkable(int x, int y);

	SDL_sem *LockReservePos, *LockFindPath, *LockFreePos, *LockGetPath;
};

